package com.gl.saasservice.sys.service;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.gl.common.util.Digests;
import com.gl.common.util.Encodes;
import com.gl.common.util.redis.RedisUtils;
import com.gl.common.util.sql.SqlUtils;
import com.gl.common.vo.ApiData;
import com.gl.framework.web.response.Result;
import com.gl.saasservice.entity.*;
import com.gl.saasservice.repository.*;
import com.gl.saasservice.sys.utils.CheckUtil;
import com.gl.saasservice.sys.vo.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserService {
    private static final Logger LOG = LoggerFactory.getLogger(UserService.class);

    @Autowired
    private UserRepository userRepository;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private DepartmentRepository departmentRepository;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private UserDepartmentRepository userDepartmentRepository;
    @Autowired
    private RoleRepository roleRepository;
	@Autowired
	private UserRoleRepository userRoleRepository;
	@Autowired
    private QYUserRepository qYUserRepository;

    public Result pages(String accessToken, Integer pageNumber, Integer pageSize, AppUserVO filter) {
        LOG.info("---UserService pages accessToken={},pageNumber={},pageSize={},userVO={}", accessToken, pageNumber, pageSize, filter);

        ApiData<AppUserVO> apiData = new ApiData<>();

        String columns = " SELECT tsu.* FROM saas_app_user tsu  "+
                " LEFT JOIN saas_user_role_ref ur ON tsu.id=ur.user_id " +
                " LEFT JOIN saas_user_department_ref ud ON tsu.id=ud.user_id  ";

        String count = " SELECT count(1) FROM ( SELECT 1 FROM saas_app_user tsu  "+
                " LEFT JOIN saas_user_role_ref ur ON tsu.id=ur.user_id " +
                " LEFT JOIN saas_user_department_ref ud ON tsu.id=ud.user_id  ";
        String offsets = " LIMIT ? OFFSET ?";

        StringBuilder where = new StringBuilder("WHERE 1 = 1 and tsu.type=2 \n");
        List<Object> args = new ArrayList<>();

        if (filter != null) {

            if (filter.getStatus() != null) {
                where.append(" AND tsu.status = ? \n");
                args.add(filter.getStatus());
            }

            if (filter.getName() != null) {
                where.append(" AND tsu.name like ? \n");
                args.add("%"+filter.getName()+"%");
            }

            if (filter.getPhone() != null) {
                where.append(" AND tsu.phone like ? \n");
                args.add("%"+filter.getPhone()+"%");
            }

            if (filter.getRoleId() != null) {
                where.append(" AND ur.role_id = ? \n");
                args.add(filter.getRoleId());
            }

            if (filter.getDepId() != null) {
                where.append(" AND ud.dep_id = ? \n");
                args.add(filter.getDepId());
            }

        }

        // 查询总记录数
        String countgroupby=" GROUP BY tsu.id ) v ";
        Long total = jdbcTemplate.queryForObject(count + where+countgroupby, Long.class, args.toArray());
        if (total == 0) {
            return Result.success(apiData);
        }
        // 查询分页数据
        String SQLgroupby=" GROUP BY tsu.id ";
        where.append(SQLgroupby).append(" ORDER BY ").append(" tsu.id desc ").append(" \n").append(offsets);
        args.add(pageSize);
        args.add(pageNumber * pageSize);
        List<AppUserVO> data = jdbcTemplate.query(columns + where, new BeanPropertyRowMapper<>(AppUserVO.class), args.toArray());

        if (data.isEmpty()) {
            return Result.success(apiData);
        }

        List<String> ids=data.stream().map(AppUserVO::getId).collect(Collectors.toList());

        // 设置机构名称、部门名称、角色名称
        List<Department> departmentList = departmentRepository.findAll();
        if (departmentList.isEmpty()) {
            return Result.success(apiData);
        }

        List<UserDepartment> userDepartmentList=userDepartmentRepository.findByUserIdIn(ids);
        List<UserDepartmentVO> userDepartmentVOList=new ArrayList<>();
        userDepartmentList.forEach(ud -> {
            UserDepartmentVO vo =new UserDepartmentVO();
            BeanUtils.copyProperties(ud,vo);
            for(Department department : departmentList){
                if(department.getId().equals(vo.getDepId())){
                    vo.setDepName(department.getName());
                }

            }
            userDepartmentVOList.add(vo);
        });

        List<String> userIdList = data.stream().map(AppUserVO::getId).collect(Collectors.toList());

        String roleSql = " SELECT tsur.USER_ID AS userId, tsur.ROLE_ID AS roleId, tsr.NAME AS roleName FROM saas_user_role_ref tsur INNER JOIN saas_role tsr ON tsur.ROLE_ID = tsr.ID " +
                " WHERE tsur.`user_id` IN " + SqlUtils.foreachIn(userIdList.size());
        List<UserRoleVO> userRoleVOList = jdbcTemplate.query(roleSql, new BeanPropertyRowMapper<>(UserRoleVO.class), userIdList.toArray());

        for (AppUserVO userVO : data) {
            for (UserRoleVO userRoleVO : userRoleVOList) {
                if (Objects.equals(userRoleVO.getUserId(), userVO.getId())) {
                    userVO.getRoleNames().add(userRoleVO.getRoleName());
                    userVO.getRoleIds().add(userRoleVO.getRoleId());
                }
            }

            for (UserDepartmentVO userDepartmentVO : userDepartmentVOList) {

                if (Objects.equals(userVO.getId(), userDepartmentVO.getUserId())) {
                    userVO.getDepIds().add(userDepartmentVO.getDepId());
                    userVO.getDepNames().add(userDepartmentVO.getDepName());
                }
            }
        }

        apiData.setData(data);
        apiData.setTotal(total);

        return Result.success(apiData);

    }

    public Result save(String accessToken, AppUserVO userVO) {
        LOG.info("---UserService save accessToken={},userVO={}", accessToken, userVO);

        CheckUtil checkUtil = new CheckUtil();
        checkUtil.checkValues(userVO);
        if (checkUtil.isNull()) {
            return Result.fail(checkUtil.getMessage());
        }

        AppUser user = new AppUser();
        BeanUtils.copyProperties(userVO,user);

        if (user.getId() == null){

            if (StringUtils.isBlank(userVO.getPassword())){
                return Result.fail("用户密码不能为空");
            }
            if (StringUtils.isBlank(userVO.getConfirmPassword())){
                return Result.fail("用户确认密码不能为空");
            }

            if (!Objects.equals(userVO.getPassword(),userVO.getConfirmPassword())){
                return Result.fail("密码和确认密码不一致");
            }
            // 验证是否已存在相同name
            AppUser userEntity = userRepository.findByName(userVO.getName());
            if (Objects.nonNull(userEntity) && !Objects.equals(user.getId(),userEntity.getId())) {
                return Result.fail("存在相同姓名的用户");
            }

            user.setRegistrationTime(new Date());

            byte[] salt = Digests.generateSalt(8);
            String saltStr = Encodes.encodeHex(salt);
            user.setSalt(saltStr);

            byte[] hashPassword = Digests.sha1(userVO.getConfirmPassword().getBytes(), salt, 1024);
            String password = Encodes.encodeHex(hashPassword);
            user.setPassword(password);
        }else {
            AppUser user1 = userRepository.findById(user.getId()).get();

            if (!Objects.equals(user.getName(), user1.getName())) {
                // 验证是否已存在相同name
                AppUser userEntity = userRepository.findByName(user.getName());
                if (Objects.nonNull(userEntity) && !Objects.equals(user.getId(), userEntity.getId())) {
                    return Result.fail("存在相同姓名的用户");
                }
            }

            if (!Objects.equals(user.getPhone(), user1.getPhone())) {
                // 验证是否已存在相同手机
                AppUser userEntity = userRepository.findByPhone(user.getPhone());
                if (Objects.nonNull(userEntity) && !Objects.equals(user.getId(), userEntity.getId())) {
                    return Result.fail("存在相同手机");
                }
            }

            user.setPassword(user1.getPassword());
            user.setSalt(user1.getSalt());

            //更新App用户信息，同步维护企业用户信息
            Optional<User> optionalEntity = qYUserRepository.findById(user.getId());
            if(optionalEntity.isPresent()){
                User entity=optionalEntity.get();
                if (!entity.getMobile().equals(user.getPhone())) {  //手机号有更新才验证
                    User e = qYUserRepository.findByMobile(user.getPhone());
                    if (e != null) {
                        return Result.fail("手机号码重复");
                    }
                }
                //验证通过
                entity.setMobile(user.getPhone());
                qYUserRepository.save(entity);
            }

        }

        AppUser save = userRepository.save(user);

    /*    userRoleRepository.deleteByUserId(save.getId());
        List<UserRole> list = new ArrayList<>();
        for (Long role : userVO.getRoleIds()) {
            UserRole userRole = new UserRole();
            userRole.setUserId(save.getId());
            userRole.setRoleId(role);
            list.add(userRole);
        }
        userRoleRepository.saveAll(list);*/

        return Result.success(null);
    }

    public Result delete(String accessToken,String id) {
        LOG.info("---UserService delete accessToken={},id={}", accessToken,id);


        Optional<AppUser> optional = userRepository.findById(id);
        if (!optional.isPresent()) {
            return Result.fail("当前角色数据不存在！");
        }
        userRoleRepository.deleteByUserId(id);
        userRepository.deleteById(id);
        userDepartmentRepository.deleteByUserId(id);

        //redisService.delUserRedis(id);

        return Result.success(null);
    }

    /**
     * 获取用户数据权限
     *
     * @return
     * @author shun
     * @date 2020年12月24日
     */
/*    public List<Long> findOrgs(Long userId) {
        try {
            if (userId == null) {
                return null;
            }
            return userDepartmentRepository.findByUserId(userId).stream().map(UserDepartment::getDepId)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }
        return null;
    }*/

    public Result role(String accessToken) {
        LOG.info("UserService role accessToken={}", accessToken);

        List<Role> roleList = roleRepository.findAll();
        if (roleList.isEmpty()) {
            return Result.success(null);
        }
        ApiData<RoleVO> apiData = new ApiData();
        for (Role role : roleList) {
            RoleVO roleVO = new RoleVO();
            BeanUtils.copyProperties(role, roleVO);
            apiData.getData().add(roleVO);
        }
        apiData.setTotal(new Long(apiData.getData().size()));
        return Result.success(apiData);
    }

    public Result departmentList(String accessToken,Long id) {
        LOG.info("---RoleService departmentList accessToken={}", accessToken);

        try {
            StringBuffer sql = new StringBuffer("SELECT * FROM saas_department ORDER BY parent_id,sortby");
            StringBuffer userDepSql = new StringBuffer("SELECT dep_id FROM saas_user_department_ref WHERE user_id = ? ORDER BY dep_id");

            List<DepartmentVO> list = jdbcTemplate.query(sql.toString(), new BeanPropertyRowMapper<>(DepartmentVO.class));
            List<Map<String, Object>> userDepList = jdbcTemplate.queryForList(userDepSql.toString(), id);

            if (list == null || list.isEmpty()) {
                return Result.success(null);
            }

    /*        List<LevelVO> levelList = findLevel("fh_sys_department");
            for (DepartmentVO departmentVO : list) {
                for (LevelVO lvo : levelList) {
                    if (departmentVO.getId().longValue() == lvo.getId().longValue()) {
                        departmentVO.setLevel(lvo.getLevel());
                    }
                }
            }*/

            checkSelect(list, userDepList, "dep_id");

            // 重排结果
            List<DepartmentVO> newList = new LinkedList<>();
            sortList(newList, list);

            return Result.success(newList);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            return Result.fail();
        }
    }

    /**
     * 排序
     *
     * @param newList
     * @param list
     * @author chensenrong
     */
    private void sortList(List<DepartmentVO> newList, List<DepartmentVO> list) {
        for (DepartmentVO vo : list) {
            if (vo.getParentId().longValue() == 0) {
                newList.add(vo);
                findChild(vo.getId(), newList, list);
            }
        }
    }

    /**
     * 递归找下级
     *
     * @param parentId
     * @param newList
     * @param list
     * @author chensenrong
     */
    private void findChild(Long parentId, List<DepartmentVO> newList, List<DepartmentVO> list) {
        for (DepartmentVO vo : list) {
            if (parentId.longValue() == vo.getParentId().longValue()) {
                newList.add(vo);
                findChild(vo.getId(), newList, list);
            }
        }
    }

    /**
     * 设置已有权限
     *
     * @param list
     * @param userDepList
     * @param permIdColumn
     * @author chensenrong
     */
    private void checkSelect(List<DepartmentVO> list, List<Map<String, Object>> userDepList, String permIdColumn) {
        for (DepartmentVO vo : list) {
            if (hasPerm(vo.getId(), userDepList, permIdColumn)) {
                vo.setCheck(true);
            } else {
                vo.setCheck(false);
            }
        }
    }

    /**
     * 判断是否拥有权限
     *
     * @param id
     * @param userDepList
     * @param permIdColumn
     * @return
     * @author chensenrong
     */
    private boolean hasPerm(Long id, List<Map<String, Object>> userDepList, String permIdColumn) {
        for (Map<String, Object> map : userDepList) {
            Object perIdObj = map.get(permIdColumn);
            if (perIdObj == null) {
                continue;
            }

            Long perId = Long.valueOf(perIdObj.toString());
            if (id.longValue() == perId.longValue()) {
                return true;
            }
        }

        return false;
    }

    public Result saveUserDepartment(String accessToken, UserDepartmentRequestVO vo ) {
        LOG.info("---UserService saveUserDepartment accessToken={},departmentIds={}", accessToken, JSON.toJSONString(vo));

        try {
            Optional<AppUser> optional = userRepository.findById(vo.getUserId());
            if (!optional.isPresent()) {
                return Result.fail("没有找到此用户");
            }

            if (vo.getDepartmentIds().isEmpty()) {
                LOG.error("---UserService.saveUserDepartment---> 授权的部门为空  departmentIds = {}", vo.getDepartmentIds());
                return Result.fail("授权的权限为空");
            } else {
                List<UserDepartment> rpList = userDepartmentRepository.findByUserId(vo.getUserId());
                userDepartmentRepository.deleteAll(rpList);

                List<UserDepartment> list = new ArrayList<>();
                for (Long id : vo.getDepartmentIds()) {
                    if (id == null) {
                        continue;
                    }
                    UserDepartment entity = new UserDepartment();
                    entity.setUserId(vo.getUserId());
                    entity.setDepId(id);
                    list.add(entity);
                }

                userDepartmentRepository.saveAll(list);

                return Result.success(null);
            }
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            return Result.fail();
        }
    }

	/**
	 * 获取用户数据权限
	 *
	 * @param
	 * @return
	 * @throws Exception
	 */
/*	public List<Long> findUserOrgIds(Long id) throws Exception {
		return jdbcTemplate.queryForList("SELECT tsud.dep_id FROM fh_sys_user_department tsud WHERE tsud.user_id = ?", Long.class, id);
	}*/
    @Transactional
    public Result changePassword(String accessToken, AppUserVO userVO) {
        LOG.info("---UserService save accessToken={},userVO={}", accessToken, userVO);

        /*if (StringUtils.isBlank(userVO.getPassword())){
            return Result.fail("用户密码不能为空");
        }*/

        if (StringUtils.isBlank(userVO.getNewPassword())){
            return Result.fail("用户新密码不能为空");
        }

        if (StringUtils.isBlank(userVO.getConfirmPassword())){
            return Result.fail("用户确认密码不能为空");
        }

        if (!Objects.equals(userVO.getNewPassword(),userVO.getConfirmPassword())){
            return Result.fail("新密码和确认密码不一致");
        }

        Optional<AppUser> byId = userRepository.findById(userVO.getId());
        if (byId.isPresent()){
            AppUser user = byId.get();

            /*byte[] hashPassword = Digests.sha1(userVO.getPassword().getBytes(),  Encodes.decodeHex(user.getSalt()), 1024);
            String password = Encodes.encodeHex(hashPassword);

            if (!StringUtils.equals(password,user.getPassword())){
                return Result.fail("用户密码不正确！");
            }*/

            if (StrUtil.isEmpty(user.getSalt()) || StrUtil.isEmpty(user.getPassword())) {
                return Result.fail("该账号没有密码！");
            }
            byte[] hashPassword1 = Digests.sha1(userVO.getConfirmPassword().getBytes(), Encodes.decodeHex(user.getSalt()), 1024);
            String password1 = Encodes.encodeHex(hashPassword1);
            user.setPassword(password1);

            userRepository.save(user);

            //维护企业用户表
            Optional<User> optionalEntity = qYUserRepository.findById(userVO.getId());
            if(optionalEntity.isPresent()) {
                User entity = optionalEntity.get();
                entity.setSalt(user.getSalt());
                entity.setPassword(password1);
                qYUserRepository.save(entity);
            }

            return Result.success(null);
        }
        return Result.fail("当前用户不存在！");
    }

    public Result UpdateStatus(String accessToken, AppUserVO filter) {
        LOG.info("UserService UpdateStatus accessToken={},filter={}",accessToken,filter);
        Optional<AppUser> userOptional = userRepository.findById(filter.getId());
        if (userOptional.isPresent()){
            AppUser user = userOptional.get();
            user.setStatus(filter.getStatus());
            userRepository.save(user);
        }
        return Result.success(null);
    }

    public Result department(String accessToken) {
        LOG.info("UserService store accessToken={}", accessToken);

        List<Department> departmentList = departmentRepository.findAll();

        if (departmentList.isEmpty()) {
            return Result.success(null);
        }

        ApiData<DepartmentVO> apiData = new ApiData();
        for (Department department : departmentList) {
            DepartmentVO departmentVO = new DepartmentVO();
            BeanUtils.copyProperties(department, departmentVO);
            apiData.getData().add(departmentVO);

        }
        apiData.setTotal(new Long(apiData.getData().size()));
        return Result.success(apiData);
    }

}
